Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

never construct value on stack in new_box_zeroed #1601

Merged
merged 1 commit into from
Sep 3, 2024

Conversation

Freax13
Copy link
Contributor

@Freax13 Freax13 commented Aug 29, 2024

On lower opt-levels the compiler might not optimize out the layout.size() == 0 branch and emits code for the if-body. This will cause a stack allocation for Self. Avoid calling new_zeroed() and directly construct the Box from a dangling pointer instead.

@codecov-commenter
Copy link

codecov-commenter commented Aug 29, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.70%. Comparing base (51c17a3) to head (71d93cf).
Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1601   +/-   ##
=======================================
  Coverage   87.70%   87.70%           
=======================================
  Files          15       15           
  Lines        5565     5565           
=======================================
  Hits         4881     4881           
  Misses        684      684           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@joshlf
Copy link
Member

joshlf commented Aug 29, 2024

Thanks for this! It looks reasonable, although I have a concern with the cited Box docs: rust-lang/unsafe-code-guidelines#529

Once that's resolved, I'll approve.

@joshlf
Copy link
Member

joshlf commented Aug 29, 2024

Blocked on rust-lang/rust#129748.

Copy link
Member

@joshlf joshlf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, rust-lang/rust#129748 merged, so we're good to continue here.

When you make changes, please squash everything together into the same commit and force-push instead of adding new commits.

src/lib.rs Outdated
Comment on lines 2131 to 2133
// SAFETY: Contructing a Box to a ZST from a dangling pointer is
// explicitly allowed:
// https://doc.rust-lang.org/std/boxed/index.html#memory-layout
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update this to abide by our safety comment policy?*

Suggested change
// SAFETY: Contructing a Box to a ZST from a dangling pointer is
// explicitly allowed:
// https://doc.rust-lang.org/std/boxed/index.html#memory-layout
// SAFETY: Per [1], when `T` is a ZST, `Box<T>`'s only validity requirements are that
// the pointer is non-null and sufficiently aligned. Per [2], `NonNull::dangling` produces
// a pointer which is sufficiently aligned. Since the produced pointer is a `NonNull`,
// it is non-null.
//
// [1] Per https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout:
//
// For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned.
//
// [2] Per https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.dangling:
//
// Creates a new `NonNull` that is dangling, but well-aligned.

(I'm sure the line wrapping on that comment is wrong - just typed in the web UI)

* This technically violates the "don't cite nightly docs" policy, but I'm comfortable that this isn't liable to change.

Comment on lines +2134 to +2151
unsafe {
return Box::from_raw(NonNull::dangling().as_ptr());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a comment that explains why we do this instead of Box::new(Self::new_zeroed())? The argument in your commit message makes sense, but I don't think it's obvious enough that we should expect future readers to figure it out from context.

On lower opt-levels the compiler might not optimize out the
`layout.size() == 0` branch and emits code for the if-body. This will
cause a stack allocation for `Self`. Avoid calling new_zeroed() and
directly construct the Box from a dangling pointer instead.

Co-authored-by: Joshua Liebow-Feeser <joshlf@users.noreply.github.com>
Copy link
Member

@joshlf joshlf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks again for putting this PR up!

@joshlf joshlf added this pull request to the merge queue Sep 3, 2024
Merged via the queue into google:main with commit e812894 Sep 3, 2024
74 checks passed
joshlf added a commit that referenced this pull request Sep 3, 2024
On lower opt-levels the compiler might not optimize out the
`layout.size() == 0` branch and emits code for the if-body. This will
cause a stack allocation for `Self`. Avoid calling new_zeroed() and
directly construct the Box from a dangling pointer instead.

Co-authored-by: Joshua Liebow-Feeser <joshlf@users.noreply.github.com>
@joshlf
Copy link
Member

joshlf commented Sep 5, 2024

Update on this: I've published 0.8.0-alpha.18, which includes this change. It should be trivial to backport to 0.7 as well (in progress in #1604), but we're having unrelated CI issues that are blocking it from merging. We probably won't have time to burn those CI issues down for at least a week or two, and possibly longer.

@Freax13
Copy link
Contributor Author

Freax13 commented Sep 5, 2024

Thanks for the update!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants